#include <stdlib.h>             /* Standard Lib    ISOC  */
#include <stdarg.h>             /* Variable args   ISOC  */
#include <stdio.h>              /* I/O lib         ISOC  */
#include <gmp.h>                /* GNU GMP Library       */
#include <math.h>
#include <pthread.h>


mpf_t  a, y, temp,temp1,temp2;
int i=0;

void * passo1(void *arg){
	
	mpf_ui_sub(temp1, 1, temp);

	return NULL;
}

void * passo2(void *arg){
	
	mpf_add_ui(temp2, temp, 1);

	return NULL;
}
void * passo3(void *arg){
	
	//a = ( a * pow((1 + y), 4) ) - ( pow(2, (2*i + 3)) * y * (1 + y + y*y) ) ;
	mpf_add_ui(temp, y, 1);
	mpf_pow_ui(temp,temp,4);
	mpf_mul(temp, temp, a);

	return NULL;
}
void * passo4(void *arg){
	
	mpf_set_d(temp1, 2);
	mpf_pow_ui(temp1,temp1,(2*i + 3));

	return NULL;
}
void * passo5(void *arg){
	
	mpf_mul(temp2, y, y);
	mpf_add(temp2, temp2, y);
	mpf_add_ui(temp2, temp2, 1);

	return NULL;
}

int main() {
	int k=11;
	pthread_t threads[5];

	//seta a precisao do ponto flutuante
	mpf_set_default_prec(1024 * 40000);




	mpf_init_set_d(temp,.0);
	mpf_init_set_d(temp1,.0);
	mpf_init_set_d(temp2,.0);

	//double a = 6 - (4*M_SQRT2);
	mpf_init(a);
	mpf_sqrt_ui(a, 2 );
	mpf_mul_ui(a,a,4);
	mpf_ui_sub(a, 6, a);


	//double y = M_SQRT2 -1;
	mpf_init(y);
	mpf_sqrt_ui(y, 2 );
	mpf_sub_ui(y,y,1);
	

	
	for(; i<k; i++) {
		//y = ( 1 - pow((1-pow(y, 4)), .25) ) / ( 1 + pow((1-pow(y, 4)), .25) ) ;
		mpf_pow_ui(temp, y, 4);
		mpf_ui_sub(temp, 1, temp);
		mpf_sqrt (temp, temp);
		mpf_sqrt (temp, temp);

		//mpf_ui_sub(temp1, 1, temp);
		pthread_create(threads , NULL, passo1, NULL);

		//mpf_add_ui(temp2, temp, 1);
		pthread_create(threads + 1, NULL, passo2, NULL);

		pthread_join( threads[0],NULL);
		pthread_join( threads[1],NULL);

		mpf_div(y, temp1,temp2);



		//a = ( a * pow((1 + y), 4) ) - ( pow(2, (2*i + 3)) * y * (1 + y + y*y) ) ;
		//mpf_add_ui(temp, y, 1);
		//mpf_pow_ui(temp,temp,4);
		//mpf_mul(temp, temp, a);
		pthread_create(threads + 2, NULL, passo3, NULL);

		//mpf_set_d(temp1, 2);
		//mpf_pow_ui(temp1,temp1,(2*i + 3));
		pthread_create(threads + 3, NULL, passo4, NULL);
		//mpf_mul(temp2, y, y);
		//mpf_add(temp2, temp2, y);
		//mpf_add_ui(temp2, temp2, 1);
		pthread_create(threads + 4, NULL, passo5, NULL);


		pthread_join( threads[2],NULL);
		pthread_join( threads[3],NULL);
		pthread_join( threads[4],NULL);

		mpf_mul(temp2, temp2, y);
		mpf_mul(temp2, temp1, temp2);
		mpf_sub(a, temp, temp2);

		
	}
	printf("\n");
	mpf_set_d(temp, 1.0 );

	//pi=1/a
	mpf_div(a, temp, a);
	mpf_out_str(NULL, 10, 10000000,a);
	printf("\n");
	

	return 0;
}